package com.ws.soa.consumer.service;

import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.util.HashSet;
import java.util.Set;

/**
 * SessionStorageClientService
 *
 * @since 2019-03-02
 */
public class RedisCacheClientService {

    private static final String STATUS_CODE = "OK";

    private JedisPool pool;

    public JedisPool getPool() {
        return pool;
    }

    public void setPool(JedisPool pool) {
        this.pool = pool;
    }

    /**
     * 存储string
     *
     * @param key
     * @param value
     * @param expireSecond 过期秒数
     */
    public void set(final String key, final String value, final int expireSecond) {
        Jedis jedis = getResource();
        try {
            if (expireSecond != -1) {
                jedis.setex(key, expireSecond, value);
            }
        } finally {
            returnResource(jedis);
        }
    }

    public String get(final String key) {
        String value = null;
        Jedis jedis = getResource();
        try {
            value = jedis.get(key);
        } finally {
            returnResource(jedis);
        }
        return value;
    }

    public Long del(final String key) {
        long value = 0;
        Jedis jedis = getResource();
        try {
            value = jedis.del(key);
        } finally {
            returnResource(jedis);
        }
        return value;
    }

    /**
     * 不存在则设置
     *
     * @param key
     * @param value
     * @param expireSecond 过期
     */
    public Long setnx(String key, String value, int expireSecond) {
        Long result;
        Jedis jedis = getResource();
        try {
            if (expireSecond == -1) {
                result = jedis.setnx(key, value);
            } else {
                String statusCode = jedis.set(key, value, "NX", "EX", expireSecond);
                // 正确状态
                if (null != statusCode && statusCode.equals(STATUS_CODE)) {
                    result = 1L;
                } else {
                    result = 0L;
                }
            }
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 将一个或多个 member 元素加入到集合 key 当中，已经存在于集合的 member 元素将被忽略。 当 key 不是集合类型时，返回一个错误。
     *
     * @param key
     * @param expireSecond
     * @param values
     * @return
     */
    public long sadd(String key, int expireSecond, String... values) {
        Long result = Long.valueOf(0);
        Jedis jedis = getResource();
        try {
            result = jedis.sadd(key, values);
            if (expireSecond != -1) {
                jedis.expire(key, expireSecond);
            }
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 判断 member 是否存在于集合中。
     *
     * @param key
     * @param member
     * @return
     */
    public boolean sismember(String key, String member) {
        Boolean result;
        Jedis jedis = getResource();
        try {
            result = jedis.sismember(key, member);
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 返回集合 key 中的所有成员。 不存在的 key 被视为空集合。
     *
     * @param key
     * @return
     */
    public Set<String> smembers(String key) {
        Set<String> result = new HashSet<>();
        Jedis jedis = getResource();
        try {
            result = jedis.smembers(key);
        } finally {
            returnResource(jedis);
        }
        return result;
    }


    /**
     * 移除并返回集合中的一个随机元素
     *
     * @param key
     * @return
     */
    public String spop(String key) {
        String result = null;
        if (key == null || key.trim().length() == 0) return result;
        Jedis jedis = null;
        try {
            jedis = getResource();
            result = jedis.spop(key);
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 返回集合key中元素数量
     *
     * @param key
     * @return key不存在，返回0
     */
    public Long scard(String key) {
        Long result = Long.valueOf(0);
        if (key == null || key.trim().length() == 0) return result;
        Jedis jedis = null;
        try {
            jedis = getResource();
            result = jedis.scard(key);
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 在list尾部插入数据
     *
     * @param key
     * @param values
     * @param expireSecond 过期
     */
    public Long rpush(String key, int expireSecond, String... values) {
        Long result;
        Jedis jedis = getResource();
        try {
            result = jedis.rpush(key, values);
            if (expireSecond != -1) {
                jedis.expire(key, expireSecond);
            }
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 从list队尾删除key对应value，返回value
     *
     * @param key
     * @return
     */
    public String rpop(String key) {
        Jedis jedis = getResource();
        String value = null;
        try {
            value = jedis.rpop(key);
        } finally {
            returnResource(jedis);
        }
        return value;
    }

    /**
     * 返回list里的长度
     *
     * @param key
     */
    public Long llen(String key) {
        Jedis jedis = getResource();
        long result;
        try {
            result = jedis.llen(key);
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 随机返回集合中的一个元素
     *
     * @param key
     * @return
     */
    public String srandmember(String key) {
        String result = null;
        if (key == null || key.trim().length() == 0) return result;
        Jedis jedis = null;
        try {
            jedis = getResource();
            result = jedis.srandmember(key);
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 移除集合 key 中的一个或多个 member 元素，不存在的 member 元素会被忽略。 当 key 不是集合类型，返回一个错误。
     *
     * @param key
     * @param values
     * @return
     */
    public long srem(String key, String... values) {
        Long result = Long.valueOf(0);
        Jedis jedis = getResource();
        try {
            result = jedis.srem(key, values);
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 以秒为单位返回 key 的剩余过期时间
     *
     * @param key
     * @return 当 key 不存在时，返回 -2 。
     * 当 key 存在但没有设置剩余生存时间时，返回 -1 。
     * 否则，以秒为单位，返回 key 的剩余生存时间。
     */
    public long ttl(String key) {
        long ret = -2;
        if (null == key || key.trim().length() == 0) return ret;
        Jedis jedis = getResource();
        try {
            ret = jedis.ttl(key.getBytes());
        } finally {
            returnResource(jedis);
        }
        return ret;
    }

    public void setCache(final String key, final Object obj, final int expireSecond) {
        //如果换成数据不存在，需要把数据缓存起来，用于容错处理
        if (null != obj) {
            final String json = JSON.toJSONString(obj);
            if (StringUtils.isNotBlank(json)) {
                this.set(key, json, expireSecond);
            }
        }
        return;
    }

    public Object getCache(final String key, final Class clazz) {
        String cache = this.get(key);
        if (StringUtils.isNotBlank(cache)) {
            return JSON.parseObject(cache, clazz);
        }
        return null;
    }

    public Jedis getResource() {
        return pool.getResource();
    }

    public void returnResource(Jedis redis) {
        if (redis != null) {
            redis.close();
        }
    }

    public void destroy() {
        if (pool != null) {
            pool.destroy();
        }
    }
}


